package hn.sigit.view;

import hn.sigit.logic.bpm.ParcelData;
import hn.sigit.logic.bpm.PropertyData;
import hn.sigit.model.hnd.cadastre.HND_Parcel;
import hn.sigit.dao.hnd.cadastre.HND_ParcelDAO;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.richfaces.model.DataProvider;
import org.richfaces.model.ExtendedTableDataModel;
import org.richfaces.model.selection.SimpleSelection;

@Name("selectParcelHelper")
@Scope(value = ScopeType.CONVERSATION)
@AutoCreate
public class SelectParcelHelper implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private List<HND_Parcel> parcels;
	private HND_Parcel selectedParcel;
	private SimpleSelection parcelSelection;
	private String propertyName;
	private List<HND_Parcel> selectedParcels = new ArrayList<HND_Parcel>();
	
	private String parcelIdField;
	private String parcelLabelField;
	private String parcelFieldTabField;
	private String parcelMunicipalKeyField;
	private String parcelCadastralKeyField;
	private String reRenderComponents;
	
	private boolean addToList = false;
	private String selectedParcelDataField;
	private String addToListMethod;

	private ExtendedTableDataModel<HND_Parcel> dataModel;

	public List<HND_Parcel> getParcels() {
		if (parcels == null) {
			parcels = HND_ParcelDAO.loadParcels();
		}
		return parcels;
	}

	public void setProperties(List<HND_Parcel> parcels) {
		this.parcels = parcels;
	}

	public HND_Parcel getSelectedParcel() {
		return selectedParcel;
	}

	public void setSelectedNaturalPerson(HND_Parcel selectedParcel) {
		this.selectedParcel = selectedParcel;
	}

	public SimpleSelection getParcelSelection() {
		return parcelSelection;
	}

	public void setParcelSelection(SimpleSelection parcelSelection) {
		this.parcelSelection = parcelSelection;
	}

	public String getPropertyName() {
		return propertyName;
	}
	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	public List<HND_Parcel> getSelectedParcels() {
		return selectedParcels;
	}
	public void setSelectedNaturalPersonParties(List<HND_Parcel> selectedParcels) {
		this.selectedParcels = selectedParcels;
	}

	public String getParcelIdField() {
		return parcelIdField;
	}
	public void setParcelIdField(String parcelIdField) {
		this.parcelIdField = parcelIdField;
	}

	public String getParcelLabelField() {
		return parcelLabelField;
	}
	public void setParcelLabelField(String parcelLabelField) {
		this.parcelLabelField = parcelLabelField;
	}

	public String getParcelFieldTabField() {
		return parcelFieldTabField;
	}
	public void setParcelFieldTabField(String parcelFieldTabField) {
		this.parcelFieldTabField = parcelFieldTabField;
	}

	public String getParcelMunicipalKeyField() {
		return parcelMunicipalKeyField;
	}
	public void setParcelMunicipalKeyField(String parcelMunicipalKeyField) {
		this.parcelMunicipalKeyField = parcelMunicipalKeyField;
	}

	public String getParcelCadastralKeyField() {
		return parcelCadastralKeyField;
	}
	public void setParcelCadastralKeyField(String parcelCadastralKeyField) {
		this.parcelCadastralKeyField = parcelCadastralKeyField;
	}
	
	public String getSelectedParcelDataField() {
		return selectedParcelDataField;
	}
	public void setSelectedParcelDataField(String selectedParcelDataField) {
		this.selectedParcelDataField = selectedParcelDataField;
	}

	public boolean isAddToList() {
		return addToList;
	}
	public void setAddToList(boolean addToList) {
		this.addToList = addToList;
	}

	public String getAddToListMethod() {
		return addToListMethod;
	}
	public void setAddToListMethod(String addToListMethod) {
		this.addToListMethod = addToListMethod;
	}

	public String getReRenderComponents() {
		return reRenderComponents;
	}
	public void setReRenderComponents(String reRenderComponents) {
		this.reRenderComponents = reRenderComponents;
	}

	public ExtendedTableDataModel<HND_Parcel> getDataModel() {
		if (dataModel == null) {
			dataModel = new ExtendedTableDataModel<HND_Parcel>(new DataProvider<HND_Parcel>() {
 
				private static final long serialVersionUID = 5054087821033164847L;

				public int getRowCount() {
					return getParcels().size();
				}
				public List<HND_Parcel> getItemsByRange(int firstRow, int endRow) {
					//TODO: Check if fetching from DB is better for memory usage
					return getParcels().subList(firstRow, endRow);
				}

				public HND_Parcel getItemByKey(Object key) {
					//TODO: Eliminar busqueda lineal
					for (HND_Parcel npp : getParcels())
						if (key.equals(getKey(npp)))
							return npp;

					return null;
				}
 
 				public Object getKey(HND_Parcel item) {
					return item.getSuID();
				}
			});
 		}
		return dataModel;
	}

	public void takeSelection(ActionEvent ae) {
		getSelectedParcels().clear();
		Iterator<Object> iterator = getParcelSelection().getKeys();
		while (iterator.hasNext()){
			Object key = iterator.next();
			selectedParcel = getDataModel().getObjectByKey(key);
			//getSelectedNaturalPersonParties().add(getNaturalPersonPartiesDataModel().getObjectByKey(key));
			if (selectedParcel != null) {
				propertyName = "LOREM IPSUM: " + selectedParcel.getLabel();
				
				Application app = FacesContext.getCurrentInstance().getApplication();
				ExpressionFactory exprFactory = app.getExpressionFactory();
				ELContext elCtx = FacesContext.getCurrentInstance().getELContext();
				
				ValueExpression ve;
				if (!addToList) {
					if (parcelIdField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + parcelIdField + "}", String.class);
						ve.setValue(elCtx, String.valueOf(selectedParcel.getSuID()));
					}
					if (parcelLabelField != null) {
						//TODO: Ver si la ficha de campo se usara siempre como el codigo
						ve = exprFactory.createValueExpression(elCtx, "#{" + parcelLabelField + "}", String.class);
						ve.setValue(elCtx, String.valueOf(selectedParcel.getLabel()));
					}
					if (parcelFieldTabField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + parcelFieldTabField + "}", String.class);
						ve.setValue(elCtx, selectedParcel.getFieldTab());
					}
					if (parcelMunicipalKeyField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + parcelMunicipalKeyField + "}", String.class);
						ve.setValue(elCtx, selectedParcel.getMunicipalKey());
					}
					if (parcelCadastralKeyField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + parcelCadastralKeyField + "}", String.class);
						ve.setValue(elCtx, selectedParcel.getCadastralKey());
					}
				}
				else {
					//adding to a list
					MethodExpression me;
					
					if (selectedParcelDataField != null && addToListMethod != null) {
						ParcelData pd = new ParcelData();
						pd.setSuID(String.valueOf(selectedParcel.getSuID()));
						pd.setLabel(selectedParcel.getLabel());
						pd.setFieldTab(selectedParcel.getFieldTab());
						pd.setMunicipalKey(selectedParcel.getMunicipalKey());
						pd.setCadastralKey(selectedParcel.getCadastralKey());
						
						ve = exprFactory.createValueExpression(elCtx, "#{" + selectedParcelDataField + "}", PropertyData.class);
						ve.setValue(elCtx, pd);
						
						//third parameter is set to null meaning that we do not care for the
						//result type... and no expected parameters for fourth parameter,
						//however we can not use null for this argument
						me = exprFactory.createMethodExpression(elCtx, "#{" + addToListMethod + "}", null, new Class[] {});
						me.invoke(elCtx, null);
					}
				}
			}
		}
	}
}
